home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / imap / non-ANSI / c-client / mtest.c < prev    next >
C/C++ Source or Header  |  1995-09-05  |  17KB  |  678 lines

  1. /*
  2.  * Program:    Mail library test program
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    8 July 1988
  13.  * Last Edited:    5 September 1995
  14.  *
  15.  * Sponsorship:    The original version of this work was developed in the
  16.  *        Symbolic Systems Resources Group of the Knowledge Systems
  17.  *        Laboratory at Stanford University in 1987-88, and was funded
  18.  *        by the Biomedical Research Technology Program of the National
  19.  *        Institutes of Health under grant number RR-00785.
  20.  *
  21.  * Original version Copyright 1988 by The Leland Stanford Junior University
  22.  * Copyright 1995 by the University of Washington
  23.  *
  24.  *  Permission to use, copy, modify, and distribute this software and its
  25.  * documentation for any purpose and without fee is hereby granted, provided
  26.  * that the above copyright notices appear in all copies and that both the
  27.  * above copyright notices and this permission notice appear in supporting
  28.  * documentation, and that the name of the University of Washington or The
  29.  * Leland Stanford Junior University not be used in advertising or publicity
  30.  * pertaining to distribution of the software without specific, written prior
  31.  * permission.  This software is made available "as is", and
  32.  * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
  33.  * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
  34.  * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  35.  * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
  36.  * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
  37.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  38.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  39.  * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
  40.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  41.  *
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <ctype.h>
  46. #include <signal.h>
  47. #include "mail.h"
  48. #include "osdep.h"
  49. #include "rfc822.h"
  50. #include "smtp.h"
  51. #include "nntp.h"
  52. #include "misc.h"
  53.  
  54. /* Excellent reasons to hate ifdefs, and why my real code never uses them */
  55.  
  56. #ifdef __MINT__
  57. # define UNIXLIKE 1
  58. # define MAC 1
  59. # define MACOS 0
  60. #else
  61. # if unix
  62. #  define UNIXLIKE 1
  63. #  define MACOS 0
  64. # else
  65. #  define USWPWD 0
  66. #  ifdef noErr
  67. #   define MAC 1
  68. #   define MACOS 1
  69. #  else
  70. #   define MAC 0
  71. #   define MACOS 0
  72. #  endif
  73. # endif
  74. #endif
  75. #if UNIXLIKE
  76. #include <pwd.h>
  77. #endif
  78. #if MAC
  79. #include <MacTCPCommonTypes.h>
  80. #include <AddressXlation.h>
  81. #endif
  82.  
  83. char *curhst = NIL;        /* currently connected host */
  84. char *curusr = NIL;        /* current login user */
  85. char personalname[MAILTMPLEN];    /* user's personal name */
  86. char userbuf[MAILTMPLEN];    /* /user= buffer */
  87.  
  88. static char *hostlist[] = {    /* SMTP server host list */
  89.   "mailhost",
  90.   "localhost",
  91.   NIL
  92. };
  93.  
  94. static char *newslist[] = {    /* Netnews server host list */
  95.   "news",
  96.   NIL
  97. };
  98.  
  99. int main  ();
  100. void mm  ();
  101. void header  ();
  102. void display_body  ();
  103. void status  ();
  104. void prompt  ();
  105. void smtptest  ();
  106.  
  107. /* Main program - initialization */
  108.  
  109. int main ()
  110. {
  111.   MAILSTREAM *stream = NIL;
  112.   char tmp[MAILTMPLEN];
  113.   long debug;
  114. #include "linkage.c"
  115. #if MACOS
  116.   {
  117.     size_t *base = (size_t *) 0x000908;
  118.                 /* increase stack size on a Mac */
  119.     SetApplLimit ((Ptr) (*base - (size_t) 65535L));
  120.   }
  121. #endif
  122. #if UNIXLIKE
  123. #ifdef __MINT__
  124.     mint_setup ();
  125. #endif
  126.   curusr = cpystr(myusername());/* current user is this name */
  127.   {
  128.     char *suffix;
  129.     struct passwd *pwd = getpwnam (curusr);
  130.     if (pwd) {
  131.       strcpy (tmp,pwd->pw_gecos);
  132.                 /* dyke out the office and phone poop */
  133.       if (suffix = strchr (tmp,',')) suffix[0] = '\0';
  134.       strcpy (personalname,tmp);/* make a permanent copy of it */
  135.     }
  136.     else personalname[0] = '\0';
  137.   }
  138. #else
  139.   curusr = cpystr ("somebody");
  140.   personalname[0] = '\0';
  141. #endif
  142.   curhst = cpystr (mylocalhost ());
  143.   mail_parameters (NIL,SET_USERNAMEBUF,(void *) userbuf);
  144.   puts ("MTest -- C client test program");
  145.   if (!*personalname) prompt ("Personal name: ",personalname);
  146.                 /* user wants protocol telemetry? */
  147.   prompt ("Debug protocol (y/n)?",tmp);
  148.   ucase (tmp);
  149.   debug = (tmp[0] == 'Y') ? T : NIL;
  150.   do {
  151.     prompt ("Mailbox ('?' for help): ",tmp);
  152.     if (!strcmp (tmp,"?")) {
  153.       puts ("Enter INBOX, mailbox name, or IMAP mailbox as {host}mailbox");
  154.       puts ("Known local mailboxes:");
  155.       mail_find (NIL,"*");
  156.       puts ("or just hit return to quit");
  157.     }
  158.     else if (tmp[0]) stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
  159.   } while (!stream && tmp[0]);
  160.   mm (stream,debug);        /* run user interface if opened */
  161. #ifdef __MINT__
  162.   mint_cleanup ();
  163. #else
  164. # if MACOS
  165.                 /* clean up resolver */
  166.   if (resolveropen) CloseResolver ();
  167. # endif
  168. #endif
  169. }
  170.  
  171. /* MM command loop
  172.  * Accepts: MAIL stream
  173.  */
  174.  
  175. void mm (stream,debug)
  176.     MAILSTREAM *stream;
  177.     long debug;
  178. {
  179.   char cmd[MAILTMPLEN],cmdx[MAILTMPLEN];
  180.   char *arg;
  181.   long i;
  182.   long last = 0;
  183.   BODY *body;
  184.   status (stream);        /* first report message status */
  185.   while (stream) {
  186.     prompt ("MTest>",cmd);    /* prompt user, get command */
  187.                 /* get argument */
  188.     if (arg = strchr (cmd,' ')) *arg++ = '\0';
  189.     switch (*ucase (cmd)) {    /* dispatch based on command */
  190.     case 'B':            /* Body command */
  191.       if (arg) last = atoi (arg);
  192.       else if (last == 0 ) {
  193.     puts ("?Missing message number");
  194.     break;
  195.       }
  196.       if (last > 0 && last <= stream->nmsgs) {
  197.     mail_fetchstructure (stream,last,&body);
  198.     if (body) display_body (body,NIL,(long) 0);
  199.     else puts ("%No body information available");
  200.       }
  201.       else puts ("?Bad message number");
  202.       break;
  203.     case 'C':            /* Check command */
  204.       mail_check (stream);
  205.       status (stream);
  206.       break;
  207.     case 'D':            /* Delete command */
  208.       if (arg) last = atoi (arg);
  209.       else {
  210.     if (last == 0) {
  211.       puts ("?Missing message number");
  212.       break;
  213.     }
  214.     arg = cmd;
  215.     sprintf (arg,"%ld",last);
  216.       }
  217.       if (last > 0 && last <= stream->nmsgs)
  218.     mail_setflag (stream,arg,"\\DELETED");
  219.       else puts ("?Bad message number");
  220.       break;
  221.     case 'E':            /* Expunge command */
  222.       mail_expunge (stream);
  223.       last = 0;
  224.       break;
  225.     case 'F':            /* Find command */
  226.       if (!arg) arg = "*";
  227.       puts ("Subscribed mailboxes:");
  228.       mail_find (NIL,arg);
  229.       puts ("Subscribed bboards:");
  230.       mail_find_bboards (NIL,arg);
  231.       puts ("Known mailboxes:");
  232.       mail_find_all (NIL,arg);
  233.       puts ("Known bboards:");
  234.       mail_find_all_bboard (NIL,arg);
  235.       if ((*stream->mailbox == '{') ||
  236.       ((*stream->mailbox == '*') && (stream->mailbox[1] == '{'))) {
  237.     puts ("Remote Subscribed mailboxes:");
  238.     mail_find (stream,arg);
  239.     puts ("Remote Subscribed bboards:");
  240.     mail_find_bboards (stream,arg);
  241.     puts ("Remote known mailboxes:");
  242.     mail_find_all (stream,arg);
  243.     puts ("Remote known bboards:");
  244.     mail_find_all_bboard (stream,arg);
  245.       }
  246.       break;
  247.     case 'G':
  248.       mail_gc (stream,GC_ENV|GC_TEXTS|GC_ELT);
  249.       break;
  250.     case 'H':            /* Headers command */
  251.       if (arg) {
  252.     if (!(last = atoi (arg))) {
  253.       mail_search (stream,arg);
  254.       for (i = 1; i <= stream->nmsgs; ++i)
  255.         if (mail_elt (stream,i)->searched) header (stream,i);
  256.       break;
  257.     }
  258.       }
  259.       else if (last == 0) {
  260.     puts ("?Missing message number");
  261.     break;
  262.       }
  263.       if (last > 0 && last <= stream->nmsgs) header (stream,last);
  264.       else puts ("?Bad message number");
  265.       break;
  266.     case 'M':
  267.       prompt ("Destination: ",cmdx);
  268.       mail_move (stream,arg,cmdx);
  269.       break;
  270.     case 'N':            /* New mailbox command */
  271.       if (!arg) {
  272.     puts ("?Missing mailbox");
  273.     break;
  274.       }
  275.                 /* get the new mailbox */
  276.       while (!(stream = mail_open (stream,arg,debug)))
  277.     prompt ("Mailbox: ",arg);
  278.       last = 0;
  279.       status (stream);
  280.       break;
  281.     case 'Q':            /* Quit command */
  282.       mail_close (stream);
  283.       stream = NIL;
  284.       break;
  285.     case 'S':            /* Send command */
  286.       smtptest (debug);
  287.       break;
  288.     case 'T':            /* Type command */
  289.       if (arg) last = atoi (arg);
  290.       else if (last == 0 ) {
  291.     puts ("?Missing message number");
  292.     break;
  293.       }
  294.       if (last > 0 && last <= stream->nmsgs) {
  295.     printf ("%s",mail_fetchheader (stream,last));
  296.     puts (mail_fetchtext (stream,last));
  297.       }
  298.       else puts ("?Bad message number");
  299.       break;
  300.     case 'U':            /* Undelete command */
  301.       if (arg) last = atoi (arg);
  302.       else {
  303.     if (last == 0 ) {
  304.       puts ("?Missing message number");
  305.       break;
  306.     }
  307.     arg = cmd;
  308.     sprintf (arg,"%ld",last);
  309.       }
  310.       if (last > 0 && last <= stream->nmsgs)
  311.     mail_clearflag (stream,arg,"\\DELETED");
  312.       else puts ("?Bad message number");
  313.       break;
  314.     case 'X':            /* Xit command */
  315.       mail_expunge (stream);
  316.       mail_close (stream);
  317.       stream = NIL;
  318.       break;
  319.     case '+':
  320.       mail_debug (stream); debug = T;
  321.       break;
  322.     case '-':
  323.       mail_nodebug (stream); debug = NIL;
  324.       break;
  325.     case '?':            /* ? command */
  326.       puts ("Body, Check, Delete, Expunge, Find, GC, Headers, Move,");
  327.       puts (" New Mailbox, Quit, Send, Type, Undelete, Xit,");
  328.       puts (" +, -, or <RETURN> for next message");
  329.       break;
  330.     case '\0':        /* null command (type next message) */
  331.       if (last > 0 && last++ < stream->nmsgs) {
  332.     printf ("%s",mail_fetchheader (stream,last));
  333.     puts (mail_fetchtext (stream,last));
  334.       }
  335.       else puts ("%No next message");
  336.       break;
  337.     default:            /* bogus command */
  338.       printf ("?Unrecognized command: %s\n",cmd);
  339.       break;
  340.     }
  341.   }
  342. }
  343.  
  344. /* MM display header
  345.  * Accepts: IMAP2 stream
  346.  *        message number
  347.  */
  348.  
  349. void header (stream,msgno)
  350.     MAILSTREAM *stream;
  351.     long msgno;
  352. {
  353.   unsigned long i;
  354.   char tmp[MAILTMPLEN];
  355.   char *t;
  356.   MESSAGECACHE *cache = mail_elt (stream,msgno);
  357.   mail_fetchstructure (stream,msgno,NIL);
  358.   tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
  359.   tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
  360.   tmp[2] = cache->flagged ? 'F' : ' ';
  361.   tmp[3] = cache->answered ? 'A' : ' ';
  362.   tmp[4] = cache->deleted ? 'D' : ' ';
  363.   sprintf (tmp+5,"%4ld) ",cache->msgno);
  364.   mail_date (tmp+11,cache);
  365.   tmp[17] = ' ';
  366.   tmp[18] = '\0';
  367.   mail_fetchfrom (tmp+18,stream,msgno,(long) 20);
  368.   strcat (tmp," ");
  369.   if (i = cache->user_flags) {
  370.     strcat (tmp,"{");
  371.     while (i) {
  372.       strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
  373.       if (i) strcat (tmp," ");
  374.     }
  375.     strcat (tmp,"} ");
  376.   }
  377.   mail_fetchsubject (t = tmp + strlen (tmp),stream,msgno,(long) 25);
  378.   sprintf (t += strlen (t)," (%ld chars)",cache->rfc822_size);
  379.   puts (tmp);
  380. }
  381.  
  382. /* MM display body
  383.  * Accepts: BODY structure pointer
  384.  *        prefix string
  385.  *        index
  386.  */
  387.  
  388. void display_body (body,pfx,i)
  389.     BODY *body;
  390.     char *pfx;
  391.     long i;
  392. {
  393.   char tmp[MAILTMPLEN];
  394.   char *s = tmp;
  395.   PARAMETER *par;
  396.   PART *part;            /* multipart doesn't have a row to itself */
  397.   if (body->type == TYPEMULTIPART) {
  398.                 /* if not first time, extend prefix */
  399.     if (pfx) sprintf (tmp,"%s%ld.",pfx,++i);
  400.     else tmp[0] = '\0';
  401.     for (i = 0,part = body->contents.part; part; part = part->next)
  402.       display_body (&part->body,tmp,i++);
  403.   }
  404.   else {            /* non-multipart, output oneline descriptor */
  405.     if (!pfx) pfx = "";        /* dummy prefix if top level */
  406.     sprintf (s," %s%ld %s",pfx,++i,body_types[body->type]);
  407.     if (body->subtype) sprintf (s += strlen (s),"/%s",body->subtype);
  408.     if (body->description) sprintf (s += strlen (s)," (%s)",body->description);
  409.     if (par = body->parameter) do
  410.       sprintf (s += strlen (s),";%s=%s",par->attribute,par->value);
  411.     while (par = par->next);
  412.     if (body->id) sprintf (s += strlen (s),", id = %s",body->id);
  413.     switch (body->type) {    /* bytes or lines depending upon body type */
  414.     case TYPEMESSAGE:        /* encapsulated message */
  415.     case TYPETEXT:        /* plain text */
  416.       sprintf (s += strlen (s)," (%ld lines)",body->size.lines);
  417.       break;
  418.     default:
  419.       sprintf (s += strlen (s)," (%ld bytes)",body->size.bytes);
  420.       break;
  421.     }
  422.     puts (tmp);            /* output this line */
  423.                 /* encapsulated message? */
  424.     if (body->type == TYPEMESSAGE && (body = body->contents.msg.body)) {
  425.       if (body->type == TYPEMULTIPART) display_body (body,pfx,i-1);
  426.       else {            /* build encapsulation prefix */
  427.     sprintf (tmp,"%s%ld.",pfx,i);
  428.     display_body (body,tmp,(long) 0);
  429.       }
  430.     }
  431.   }
  432. }
  433.  
  434. /* MM status report
  435.  * Accepts: MAIL stream
  436.  */
  437.  
  438. void status (stream)
  439.     MAILSTREAM *stream;
  440. {
  441.   long i;
  442.   char date[50];
  443.   rfc822_date (date);
  444.   puts (date);
  445.   if (stream) {
  446.     if (stream->mailbox)
  447.       printf (" %s mailbox: %s, %ld messages, %ld recent\n",
  448.           stream->dtb->name,stream->mailbox,stream->nmsgs,stream->recent);
  449.     else puts ("%No mailbox is open on this stream");
  450.     if (stream->user_flags[0]) {
  451.       printf ("Keywords: %s",stream->user_flags[0]);
  452.       for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
  453.     printf (", %s",stream->user_flags[i]);
  454.       puts ("");
  455.     }
  456.   }
  457. }
  458.  
  459.  
  460. /* Prompt user for input
  461.  * Accepts: pointer to prompt message
  462.  *          pointer to input buffer
  463.  */
  464.  
  465. void prompt (msg,txt)
  466.     char *msg;
  467.     char *txt;
  468. {
  469.   printf ("%s",msg);
  470.   gets (txt);
  471. }
  472.  
  473. /* Interfaces to C-client */
  474.  
  475.  
  476. void mm_searched (stream,number)
  477.     MAILSTREAM *stream;
  478.     long number;
  479. {
  480. }
  481.  
  482.  
  483. void mm_exists (stream,number)
  484.     MAILSTREAM *stream;
  485.     long number;
  486. {
  487. }
  488.  
  489.  
  490. void mm_expunged (stream,number)
  491.     MAILSTREAM *stream;
  492.     long number;
  493. {
  494. }
  495.  
  496.  
  497. void mm_flags (stream,number)
  498.     MAILSTREAM *stream;
  499.     long number;
  500. {
  501. }
  502.  
  503.  
  504. void mm_notify (stream,string,errflg)
  505.     MAILSTREAM *stream;
  506.     char *string;
  507.     long errflg;
  508. {
  509.   mm_log (string,errflg);
  510. }
  511.  
  512.  
  513. void mm_mailbox (string)
  514.     char *string;
  515. {
  516.   putchar (' ');
  517.   puts (string);
  518. }
  519.  
  520.  
  521. void mm_bboard (string)
  522.     char *string;
  523. {
  524.   putchar (' ');
  525.   puts (string);
  526. }
  527.  
  528. void mm_log (string,errflg)
  529.     char *string;
  530.     long errflg;
  531. {
  532.   switch ((short) errflg) {
  533.   case NIL:
  534.     printf ("[%s]\n",string);
  535.     break;
  536.   case PARSE:
  537.   case WARN:
  538.     printf ("%%%s\n",string);
  539.     break;
  540.   case ERROR:
  541.     printf ("?%s\n",string);
  542.     break;
  543.   }
  544. }
  545.  
  546.  
  547. void mm_dlog (string)
  548.     char *string;
  549. {
  550.   puts (string);
  551. }
  552.  
  553.  
  554. void mm_login (host,user,pwd,trial)
  555.     char *host;
  556.     char *user;
  557.     char *pwd;
  558.     long trial;
  559. {
  560.   char tmp[MAILTMPLEN];
  561.   if (curhst) fs_give ((void **) &curhst);
  562.   curhst = (char *) fs_get (1+strlen (host));
  563.   strcpy (curhst,host);
  564.   if (*userbuf) {
  565.     curusr = cpystr (strcpy (user,userbuf));
  566.     printf ("{%s/user=%s} ",host,user);
  567.   }
  568.   else {
  569.     sprintf (tmp,"{%s} username: ",host);
  570.     prompt (tmp,user);
  571.   }
  572.   if (curusr) fs_give ((void **) &curusr);
  573.   curusr = cpystr (user);
  574.   prompt ("password: ",pwd);
  575. }
  576.  
  577.  
  578. void mm_critical (stream)
  579.     MAILSTREAM *stream;
  580. {
  581. }
  582.  
  583.  
  584. void mm_nocritical (stream)
  585.     MAILSTREAM *stream;
  586. {
  587. }
  588.  
  589.  
  590. long mm_diskerror (stream,errcode,serious)
  591.     MAILSTREAM *stream;
  592.     long errcode;
  593.     long serious;
  594. {
  595. #if UNIXLIKE
  596.   kill (getpid (),SIGSTOP);
  597. #else
  598.   abort ();
  599. #endif
  600.   return NIL;
  601. }
  602.  
  603.  
  604. void mm_fatal (string)
  605.     char *string;
  606. {
  607.   printf ("?%s\n",string);
  608. }
  609.  
  610. /* SMTP tester */
  611.  
  612. void smtptest (debug)
  613.     long debug;
  614. {
  615.   SMTPSTREAM *stream = NIL;
  616.   char line[MAILTMPLEN];
  617.   unsigned char *text = (unsigned char *) fs_get (8*MAILTMPLEN);
  618.   ENVELOPE *msg = mail_newenvelope ();
  619.   BODY *body = mail_newbody ();
  620.   msg->from = mail_newaddr ();
  621.   msg->from->personal = cpystr (personalname);
  622.   msg->from->mailbox = cpystr (curusr);
  623.   msg->from->host = cpystr (curhst);
  624.   msg->return_path = mail_newaddr ();
  625.   msg->return_path->mailbox = cpystr (curusr);
  626.   msg->return_path->host = cpystr (curhst);
  627.   prompt ("To: ",line);
  628.   rfc822_parse_adrlist (&msg->to,line,curhst);
  629.   if (msg->to) {
  630.     prompt ("cc: ",line);
  631.     rfc822_parse_adrlist (&msg->cc,line,curhst);
  632.   }
  633.   else {
  634.     prompt ("Newsgroups: ",line);
  635.     if (*line) msg->newsgroups = cpystr (line);
  636.     else {
  637.       mail_free_body (&body);
  638.       mail_free_envelope (&msg);
  639.       fs_give ((void **) &text);
  640.     }
  641.   }
  642.   prompt ("Subject: ",line);
  643.   msg->subject = cpystr (line);
  644.   puts (" Msg (end with a line with only a '.'):");
  645.   body->type = TYPETEXT;
  646.   *text = '\0';
  647.   while (gets (line)) {
  648.     if (line[0] == '.') {
  649.       if (line[1] == '\0') break;
  650.       else strcat ((char *) text,".");
  651.     }
  652.     strcat ((char *) text,line);
  653.     strcat ((char *) text,"\015\012");
  654.   }
  655.   body->contents.text = text;
  656.   rfc822_date (line);
  657.   msg->date = (char *) fs_get (1+strlen (line));
  658.   strcpy (msg->date,line);
  659.   if (msg->to) {
  660.     puts ("Sending...");
  661.     if (stream = smtp_open (hostlist,debug)) {
  662.       if (smtp_mail (stream,"MAIL",msg,body)) puts ("[Ok]");
  663.       else printf ("[Failed - %s]\n",stream->reply);
  664.     }
  665.   }
  666.   else {
  667.     puts ("Posting...");
  668.     if (stream = nntp_open (newslist,debug)) {
  669.       if (nntp_mail (stream,msg,body)) puts ("[Ok]");
  670.       else printf ("[Failed - %s]\n",stream->reply);
  671.     }
  672.   }
  673.   if (stream) smtp_close (stream);
  674.   else puts ("[Can't open connection to any server]");
  675.   mail_free_envelope (&msg);
  676.   mail_free_body (&body);
  677. }
  678.